/*
 * Lenovo Group
 * Copyright (c) 2015-2016 All Rights Reserved.
 * 
 * Project Name:itsm-gateway
 * Create Time: 2016年2月4日 下午9:37:05
 */
package com.lenovo.lmrp.server.itsmgateway.repository;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import javax.inject.Named;

import com.fasterxml.jackson.core.type.TypeReference;
import com.google.inject.Inject;
import com.lenovo.lmrp.api.model.entity.AttachmentPO;
import com.lenovo.lmrp.api.model.entity.AttachmentPO.AttachmentStatus;
import com.lenovo.lmrp.api.model.entity.AttachmentPO.AttachmentType;
import com.lenovo.lmrp.api.model.entity.TicketExtensePO;
import com.lenovo.lmrp.api.model.entity.TicketPO;
import com.lenovo.lmrp.api.model.entity.TicketPartsPO;
import com.lenovo.lmrp.api.model.view.AttachmentVO;
import com.lenovo.lmrp.server.itsmgateway.adapter.AItsmAdapterFactory;
import com.lenovo.lmrp.server.itsmgateway.domain.ticket.AttachmentBO;
import com.lenovo.lmrp.server.itsmgateway.domain.ticket.ITicketRepository;
import com.lenovo.lmrp.server.itsmgateway.domain.ticket.TicketBO;
import com.lenovo.sdc.framework.annotation.DomainRepository;
import com.lenovo.sdc.framework.dao.ADaoFactory;
import com.lenovo.sdc.framework.dao.ICommonDAO;
import com.lenovo.sdc.framework.util.CommonUtil;
import com.lenovo.sdc.framework.util.EncryptUtil;
import com.lenovo.sdc.framework.util.JSONHelper;
import com.lenovo.sdc.framework.util.exception.ErrorCode;
import com.lenovo.sdc.framework.util.exception.TraceableException;

/**
 * 
 * @author wujin
 * @version v1.0
 */
@Named
@DomainRepository
public class TicketRepository implements ITicketRepository {
    
    private AItsmAdapterFactory adapterFactory;
    
    @Inject
    public void set(AItsmAdapterFactory adapterFactory) {
        this.adapterFactory = adapterFactory;
    }
    
    @Override
    public AttachmentBO createAttachmentBO(String itsmCode, String attacmentID) {
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            AttachmentPO po = dao.get(AttachmentPO.class, attacmentID);
            if (Objects.isNull(po)) 
                return null;
            else
                return new AttachmentBO(adapterFactory.getAdapter(itsmCode), itsmCode, po);
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_INSERT_FAILED, exp);
        }
    }
    
    @Override
    public AttachmentBO createAttachmentBO(String itsmCode, String ticketid, AttachmentVO attachmentVO) {
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            AttachmentPO po = null;
            if(CommonUtil.nonNullAndEmpty(attachmentVO.getId())){
                po = dao.get(AttachmentPO.class, attachmentVO.getId());
            }
            if (Objects.isNull(po)) {
                po = new AttachmentPO();
                po.setId(Objects.isNull(attachmentVO.getId()) ? EncryptUtil.getUUID() : attachmentVO.getId());
                po.setCreateTime(new Date());
                po.setTicketId(ticketid);
                po.setFileName(attachmentVO.getName());
                po.setStorePath(attachmentVO.getPath());
                po.setOriginalPath(attachmentVO.getOriginal());
                po.setTag(attachmentVO.getTag());
                po.setStatus(AttachmentStatus.values()[attachmentVO.getStatus()]);
                po.setSubmitter(attachmentVO.getSubmitter());
                po.setType(AttachmentType.values()[attachmentVO.getType()]);
                dao.beginTrans();
                dao.save(po);
                dao.endTrans();
            }

            return new AttachmentBO(adapterFactory.getAdapter(itsmCode), itsmCode, po);
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_INSERT_FAILED, exp);
        }
    }
    
    @Override
    public AttachmentBO createAttachmentBO(String itsmCode, AttachmentPO attachmentPO) {
        return new AttachmentBO(adapterFactory.getAdapter(itsmCode), itsmCode, attachmentPO);
    }
    
    @Override
    public boolean storeSyncTicket(String itsmCode, TicketPO ticketPO) {
        boolean isNew = true;
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            dao.beginTrans();

            // check ticketPO is new recroed or updated record
            TicketPO oldPO = dao.get(TicketPO.class, ticketPO.getId());
            if (Objects.isNull(oldPO)) {
                ticketPO.setStartTime(new Date());
                ticketPO.setUpdateTime(new Date());
                dao.save(ticketPO);

                // save ticket extense and sla information
                if (Objects.nonNull(ticketPO.getOthers()))
                    dao.save(ticketPO.getOthers());

                if (Objects.nonNull(ticketPO.getTicketSla()) && ticketPO.getTicketSla().size() > 0) {
                    ticketPO.getTicketSla().forEach(sla -> dao.save(sla));
                }

                isNew = true;
            }
            else {
                oldPO.setUpdateTime(new Date());
                oldPO.setDescription(ticketPO.getDescription());
                oldPO.setCaption(ticketPO.getCaption());
                dao.update(oldPO);
                
                // update extense
                if (Objects.nonNull(ticketPO.getOthers())) {
                    TicketExtensePO extensePO = dao.get(TicketExtensePO.class, ticketPO.getId());
                    if (Objects.nonNull(extensePO)) {
                    	Map<String, Object> newExtense = JSONHelper.fromJSON(ticketPO.getOthers().getExtprops(), 
                                new TypeReference<Map<String, Object>>() {});
                    	
                        //check ticket surveynote has changed
                        if (Objects.nonNull(newExtense.get("surveynote"))  && !extensePO.getAttributeBean().getAttribute("surveynote", "").equals(newExtense.get("surveynote").toString())) {
                        	extensePO.getAttributeBean().addAttribute("surveynotechanged", 1);
                        	extensePO.getAttributeBean().addAttribute("changenottobeview", 1);
                        }
                        
                        for(Map.Entry<String, Object> entry : newExtense.entrySet()) {
                            extensePO.getAttributeBean().addAttribute(entry.getKey(), entry.getValue());
                        }
                        extensePO.setExtprops(extensePO.getAttributeBean().dump());
                        dao.update(extensePO);
                    }
                    else
                        dao.save(ticketPO.getOthers());
                }

                isNew = false;
            }

            dao.endTrans();

            return isNew;
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_INSERT_FAILED, exp);
        }
    }
    
    @Override
    public void storeTicketAttachment(String itsmCode, AttachmentPO attachmentPO) {
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            
            dao.beginTrans();
            attachmentPO.setUpdateTime(new Date());
            dao.saveOrUpdate(attachmentPO);
            dao.endTrans();
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_INSERT_FAILED, exp);
        }
    }

    @Override
    public TicketBO createTicketBO(String itsmCode, String ticketID) {
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            TicketPO po = dao.get(TicketPO.class, ticketID);
            if (Objects.isNull(po)) 
                return null;
            else
                return new TicketBO(adapterFactory.getAdapter(itsmCode), itsmCode, po);
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_INSERT_FAILED, exp);
        }
    }

    @Override
    public void storeTicketParts(String itsmCode, List<TicketPartsPO> ticketPartsList) {
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            
            dao.beginTrans();
            for (TicketPartsPO po : ticketPartsList)
                dao.saveOrUpdate(po);
            dao.endTrans();
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_INSERT_FAILED, exp);
        }
    }

    @Override
    public TicketBO createTicketBOWithExtense(String itsmCode, String ticketID) {
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            TicketPO po = dao.get(TicketPO.class, ticketID);
            if (Objects.isNull(po)) 
                return null;
            else {
                TicketExtensePO extensePO = dao.get(TicketExtensePO.class, ticketID);
                po.setOthers(extensePO);
                return new TicketBO(adapterFactory.getAdapter(itsmCode), itsmCode, po);
            }
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_INSERT_FAILED, exp);
        }
    }

    @Override
    public void storeTicketWithExtense(String itsmCode, TicketPO ticketPO) {
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            
            dao.beginTrans();
            dao.update(ticketPO);
            if (Objects.nonNull(ticketPO.getOthers())) {
                ticketPO.getOthers().setExtprops(ticketPO.getOthers().getAttributeBean().dump());
                dao.saveOrUpdate(ticketPO.getOthers());
            }
            dao.endTrans();
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_INSERT_FAILED, exp);
        }
    }
    
    @Override
    public void storeTicketSLA(String itsmCode, String ticketid){
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            String sql = "update itsm_ticket_sla set finished = 0 where ticketid = ?";
            dao.executeSQL(sql,new String[] {ticketid});
        } catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_UPDATE_FAILED, exp);
        }
    }
    
    @Override
    public TicketPO getTicketPO(String itsmCode,String ticketid){
        try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            TicketPO ticketPO = dao.get(TicketPO.class, ticketid);
            if (Objects.isNull(ticketPO)) {
                return null;
            }
            else {
                TicketExtensePO ticketExtensePO = dao.get(TicketExtensePO.class, ticketid);
                ticketPO.setOthers(ticketExtensePO);
                return ticketPO;
            }
        }catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_QUERY_FAILED, exp);
        }
    }
    
    /* (non-Javadoc)
     * @see com.lenovo.lmrp.server.itsmgateway.domain.ticket.ITicketRepository#storeTicketOnlyExtense(java.lang.String, com.lenovo.lmrp.api.model.entity.TicketPO)
     */
    @Override
    public void storeTicketOnlyExtense(String itsmCode, TicketPO ticketPO) {
    	try (ICommonDAO dao = ADaoFactory.getDefault().createDAO(itsmCode)) {
            
            dao.beginTrans();
            if (Objects.nonNull(ticketPO.getOthers())) {
                ticketPO.getOthers().setExtprops(ticketPO.getOthers().getAttributeBean().dump());
                dao.saveOrUpdate(ticketPO.getOthers());
            }
            dao.endTrans();
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.DB_UPDATE_FAILED, exp);
        }
    }
}
